<?php

declare(strict_types=1);

namespace App\Controller;

use App\Common\Tools\DbTools;
use App\Constants\ErrorCode;
use App\Model\Aftersale;
use App\Model\AftersaleProduct;
use App\Model\FlyOrder;
use App\Model\FlyOrderProduct;
use App\Model\FlyPayOrder;
use App\Service\AdvancePayService;
use App\Service\AftersaleSetService;
use App\Service\FlyOrderProductService;
use App\Service\FlyOrderService;
use App\Service\FlyPayOrderService;
use App\Service\PayService;
use Hyperf\Redis\Redis;
use Hyperf\Utils\ApplicationContext;
use Hyperf\Utils\Coroutine;
use Hyperf\Utils\Parallel;
use Hyperf\Utils\WaitGroup;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Psr\Http\Message\ResponseInterface;
use Hyperf\Di\Annotation\Inject;
use Swoole\Coroutine\Channel;
use Yansongda\Pay\Pay;

/**
 * 用户订单
 * Class OrderController
 * @package App\Controller
 */
class OrderController extends AbstractController
{
    /**
     * @Inject
     * @var AftersaleSetService
     */
    private $reasonSet;

    /**
     * @Inject
     * @var FlyOrderService
     */
    private $flyOrder;

    /**
     * @Inject
     * @var FlyOrderProductService
     */
    private $flyOrderProduct;

    /**
     * @Inject
     * @var PayService
     */
    private $payService;

    /**
     * 获取用户ID
     * @return int
     */
    public function get_user_id(): int
    {
        return (int)$this->getAdminId() ?? 0;
    }

    /**
     * 确认订单
     * @return ResponseInterface
     */
    public function confirmOrder(): ResponseInterface
    {
        $user_id = $this->get_user_id();
        if (empty($user_id)) {
            return $this->jsonResponse->error(ErrorCode::NORMAL_ERROR, '未登录请先登录');
        }
        $verified_res = $this->flyOrder->createVerify($user_id, false);
        if (!$verified_res['res']) {
            return $this->jsonResponse->error(ErrorCode::NORMAL_ERROR, $verified_res['msg']);
        }
        return $this->jsonResponse->success($verified_res['data'], '获取确认信息ok');
    }

    /**
     * 用户下单
     * @return ResponseInterface
     */
    public function createOrder(): ResponseInterface
    {
        $user_id = $this->get_user_id();
        if (empty($user_id)) {
            return $this->jsonResponse->error(ErrorCode::NORMAL_ERROR, '未登录请先登录');
        }
        try {
            $order_lock = "order_lock:" . $user_id;
            $redis = ApplicationContext::getContainer()->get(Redis::class);
            if ($redis->get($order_lock) > 1) {
                return $this->jsonResponse->error(ErrorCode::NORMAL_ERROR, '操作频繁:请' . $redis->ttl($order_lock) . "秒后重试");
            }
            $redis->incr($order_lock);
            $redis->expire($order_lock, 30);// 30秒后重试

            $verified_res = $this->flyOrder->createVerify($user_id);
            if (!$verified_res['res']) {
                return $this->jsonResponse->error(ErrorCode::NORMAL_ERROR, $verified_res['msg']);
            }
            $verified_res['data']['user_id'] = $user_id;
            $pay_order_sn = $this->flyOrder->createOrder($verified_res['data'], true);
            if (!$pay_order_sn) {
                return $this->jsonResponse->error(ErrorCode::NORMAL_ERROR, '下单失败');
            }

        } catch (NotFoundExceptionInterface $e) {
            echo $e->getMessage();
            return $this->jsonResponse->error(ErrorCode::NORMAL_ERROR, '下单失败1');
        } catch (ContainerExceptionInterface $e) {
            echo $e->getMessage();
            return $this->jsonResponse->error(ErrorCode::NORMAL_ERROR, '下单失败2');
        } catch (\Throwable $exception) {
            echo $exception->getMessage();
            // 程序异常释放锁
            if (isset($redis)) {
                $redis->del($order_lock);
            }
            return $this->jsonResponse->error(ErrorCode::NORMAL_ERROR, '下单失败3:' . $exception->getMessage());
        }
        $redis->del($order_lock);// 删除锁
        return $this->jsonResponse->success(['pay_order_sn' => $pay_order_sn], '下单成功');
    }

    /**
     * 用户订单列表
     * @return ResponseInterface
     */
    public function getMyOrder(): ResponseInterface
    {
        // 两种格式（未付款的订单：多商家为合并展示：分别计算小计）（已付款订单：多个商家分别列表展示）
        $user_id = $this->get_user_id();
        if (empty($user_id)) {
            return $this->jsonResponse->success([], '未登录');
        }
        $params = $this->request->all();
        $order_list = $this->flyOrder->getOrderList($user_id, $params);
        $list = $this->paginate($order_list)->toArray();
        foreach ($list['data'] as &$datum) {

            if (!empty($datum['with_shop_order'])) {
                $datum['with_shop_order'][0]['virtual_form_info_arr'] = empty($datum['with_shop_order'][0]['virtual_form_info']) ? [] : json_decode($datum['with_shop_order'][0]['virtual_form_info'], true);
            } else {
                $datum['virtual_form_info_arr'] = empty($datum['virtual_form_info']) ? [] : json_decode($datum['virtual_form_info'], true);
            }

            // 虚拟订单名称
            if ($datum['order_style'] == 2) {
                $datum['sku_name'] = "";
                $arr = json_decode($datum['virtual_form_info'], true);
                if (!empty($arr)) {
                    $datum['sku_name'] .= date("m月d日,H:i", $arr['date_time']) . ',' . $arr['people_num'] . "人," . ($arr['is_vip'] ? "包间" : "大厅");
                    $datum['sku_img'] = $arr['logo'] ?? "";
                }
            }

            // 展示全部查询对应商品信息
            if (empty($params['status']) && ($datum['order_status'] == FlyOrderService::STATUS_WAIT_PAY || $datum['order_status'] == FlyOrderService::STATUS_CLOSED)) {
                unset($datum['with_products']);
                $datum['with_products'] = $this->flyOrderProduct->getProductByPayOrderId($datum['order_id']);
            }
        }
        return $this->jsonResponse->success($list, 'ok!');
    }

    /**
     * 获取订单详情
     * @return ResponseInterface
     */
    public function getDetails(): ResponseInterface
    {
        $user_id = $this->get_user_id();
        if (empty($user_id)) {
            return $this->jsonResponse->success([], '未登录请先登录');
        }
        $order_id = (int)$this->request->input('order_id', 0);
        $details = $this->flyOrder->getDetails($user_id, $order_id);
        $lat = (float)$this->request->input('lat', 0);
        $lng = (float)$this->request->input('lng', 0);
        if (!empty($lat) && !empty($lng) && !empty($details)) {
            if (!empty($details['with_shop_order'])) {
                foreach ($details['with_shop_order'] as &$detail) {
                    $detail['delivery_distance'] = DbTools::getPointDistance($lng, $lat, floatval($detail['with_shop']['lng']), floatval($detail['with_shop']['lat']));
                }
            } else {
                $details['delivery_distance'] = DbTools::getPointDistance($lng, $lat, floatval($details['with_shop']['lng']), floatval($details['with_shop']['lat']));
            }
        }
        // 订座商品
        if (!empty($details) && $details['order_style'] == 2) {
            $details['sku_name'] = "";
            if (!empty($details['with_shop_order'])) {
                $arr = $details['with_shop_order'][0]['virtual_form_info_arr'] ?? [];
            } else {
                $arr = $details['virtual_form_info_arr'] ?? [];
            }
            if (!empty($arr)) {
                $details['sku_name'] .= date("m月d日,H:i", $arr['date_time']) . ',' . $arr['people_num'] . "人," . ($arr['is_vip'] ? "包间" : "大厅");
                $details['sku_img'] = $arr['logo'] ?? "";
            }
        }
        return $this->jsonResponse->success($details, 'success');
    }

    /**
     * 订单支付
     * @return ResponseInterface
     */
    public function pay(): ResponseInterface
    {
        $user_id = $this->get_user_id();
        if (!$user_id) {
            return $this->jsonResponse->error(ErrorCode::NORMAL_ERROR, '未登录请先登录');
        }
        $params = $this->request->all();
        $pay_service = $this->payService;
        // 支付参数验证
        $pay_v = $pay_service->payVerify($params);
        if (!$pay_v['res']) {
            return $this->jsonResponse->error(ErrorCode::NORMAL_ERROR, $pay_v['msg']);
        }
        $pay_res = $pay_service->submit($pay_v['data']);
        return $this->jsonResponse->success($pay_res);
    }

    /**
     * 取消订单
     * @return ResponseInterface
     */
    public function close(): ResponseInterface
    {
        $user_id = $this->get_user_id();
        if (empty($user_id)) {
            return $this->jsonResponse->error(ErrorCode::NORMAL_ERROR, '未登录请先登录');
        }
        $pay_order_sn = $this->request->input('pay_order_sn', '');
        $reason_id = (int)$this->request->input('close_reason_id', 0);
        $is_return = (int)$this->request->input('return_cart', 0);
        $res = $this->flyOrder->cancelOrder($user_id, $pay_order_sn, $reason_id, $is_return);
        if (!$res) {
            return $this->jsonResponse->error(ErrorCode::NORMAL_ERROR, '操作失败');
        }
        return $this->jsonResponse->success([], '操作成功');
    }

    /**
     * 确认签收订单
     * @return ResponseInterface
     */
    public function receiveOrder(): ResponseInterface
    {
        $user_id = $this->get_user_id();
        if (empty($user_id)) {
            return $this->jsonResponse->error(ErrorCode::NORMAL_ERROR, '未登录请先登录');
        }
        $sn = (string)$this->request->input('order_sn', '');
        if (!$this->flyOrder->receive($user_id, $sn)) {
            return $this->jsonResponse->error(ErrorCode::NORMAL_ERROR, 'fail!');
        }
        return $this->jsonResponse->success([], 'success!');
    }

    /**
     * 删除订单
     * @return ResponseInterface
     */
    public function deleteOrder(): ResponseInterface
    {
        $user_id = $this->get_user_id();
        if (empty($user_id)) {
            return $this->jsonResponse->error(ErrorCode::NORMAL_ERROR, '未登录请先登录');
        }
        $pay_order_sn = $this->request->input('pay_order_sn', '');
        $this->flyOrder->deleteOrder($pay_order_sn, $user_id);
        return $this->jsonResponse->success([], 'success');
    }

    /**
     * 获取订单取消原因
     * @return ResponseInterface
     */
    public function getOrderReason(): ResponseInterface
    {
        $user_id = $this->get_user_id();
        if (empty($user_id)) {
            return $this->jsonResponse->success([], '未登录');
        }
        $model_type = (int)$this->request->input('model_type', AftersaleSetService::MODEL_TYPE_SHOP);
        return $this->jsonResponse->success($this->reasonSet->getOrderReason(AftersaleSetService::TYPE_ORDER_CANCEL, $model_type), 'ok!');
    }

    /**
     * 获取订单物流信息
     * @return ResponseInterface
     */
    public function getExpress()
    {
        $user_id = $this->get_user_id();
        if (empty($user_id)) {
            return $this->jsonResponse->success([], '未登录');
        }
        // 1商家列表 2用户列表
        $from = (int)$this->request->input('from', 2);
        $from = $from == 2 ? 2 : 1;
        $order_id = (int)$this->request->input('order_id', 0);
        if ($from == 1) {
            $user_id = (int)$this->request->input('from_user_id', 0);
        }
        $details = $this->flyOrder->getDetails($user_id, $order_id);
        return $this->jsonResponse->success($details['with_delivery_log'] ?? [], 'success');
    }


    /**
     * 模拟支付
     */
    public function simulate()
    {

        $sn = (string)$this->request->input('order_sn', '');

        $order_info = make(FlyPayOrder::class)->where(['pay_order_sn' => $sn])->first();
        $order = empty($order_info) ? [] : $order_info->toArray();
        if (empty($order)) {
            return $this->jsonResponse->error(ErrorCode::NORMAL_ERROR, '订单号错误');
        }
        $sn_re = make(AdvancePayService::class)->generateOuterSn([
            'pay_type' => 'alipay',
            'type' => 1,//2保证金订单 1用户商城订单 3达达商户充值订单
            'order_price' => $order['pay_price'],
            'pay_price' => $order['pay_price'],
            'pay_method' => 'scan',
            'order_sn' => $sn
        ]);
        if (empty($sn_re)) {
            return $this->jsonResponse->error(ErrorCode::NORMAL_ERROR, '参数错误');
        }

        $notify_params = [
            'out_trade_no' => $sn_re,
            'paymethod' => 'scan'
        ];
        make(PayService::class)->notify('alipay', $notify_params);
        return $this->jsonResponse->success([], '支付成功');
    }

    /**
     * 历史购买过的商品
     * @return ResponseInterface
     */
    public function getHasBuy(): ResponseInterface
    {
        $user_id = (int)$this->getAdminId() ?? 0;
        $shop_id = (int)$this->request->input('shop_id', 0);
        $order_style = (int)$this->request->input('order_style', 1);
        return $this->jsonResponse->success($this->paginate($this->flyOrder->getHasBuy($user_id, $shop_id, $order_style)), 'success');
    }

    /**
     * 清除订单数据
     */
    public function clearMyOrder()
    {

//        $num = (int)$this->request->input('num', 1);
//
//        $name = $this->request->input('name', '');
//        var_dump(apcu_add("name2", $name, 30));


//        new Parallel(5);

//        var_dump(Coroutine::inCoroutine());
//        $wg = new WaitGroup();
//        $wg->add(2);
//        co(function () use ($wg) {
//            sleep(5);
//            echo "子协程1完毕";
//            $wg->done();
//        });
//        co(function () use ($wg) {
//            echo "子协程2完毕";
//            $wg->done();
//        });
//        echo "主协程阻塞中。。。";
//        $wg->wait();
//        echo "主协程继续执行。。。";


        //        $channel = new Channel();
//        $num++;
//        defer(function () {
//            echo "先入栈：后出";
//        });
//        co(function () use ($channel, $num) {
//            $channel->push(['res' => $num * $num]);
//            defer(function () {
//                echo "后入栈：先出";
//            });
//        });
//        $data = $channel->pop();
//        return $this->jsonResponse->success($data, 'success');

//        $user_id = (int)$this->getAdminId() ?? 0;
//        $pay_order_ids = FlyPayOrder::where(['user_id' => $user_id])->pluck('pay_order_id');
//        // 清空订单
//        FlyPayOrder::whereIn('pay_order_id', $pay_order_ids)->delete();
//        FlyOrder::whereIn('pay_order_id', $pay_order_ids)->delete();
//        FlyOrderProduct::whereIn('pay_order_id', $pay_order_ids)->delete();
//        // 清空售后单
//        $af_ids = Aftersale::where(['user_id' => $user_id])->pluck('af_id');
//        Aftersale::where(['user_id' => $user_id])->delete();
//        AftersaleProduct::whereIn('af_id', $af_ids)->delete();
    }
}